package ua.kpi_java_training5.alekseenko.src.module1;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;

public class DivideInColumn {

	/**
     *
     * The class divides two integer number in column
     *
     * @autor Aleksey Alekssenko
     * @version 1.10
     * @since 2013-05-14
     *
	 */
    public static int dividend;
    public static int divisor;
    public static ArrayList<String> pseudographics = new ArrayList<String>();
    public static String integerResult;
    public static int reminder;
    public static int cursor;

    public static void main(String[] args) throws NumberFormatException, IOException{
		dividend = input("dividend");
		divisor = input("divisor");
        try{
            isNegativeSign();
            isDividendLessZero();
            dividend = Math.abs(dividend);
            divisor = Math.abs(divisor);
            reminder = intermediateCounting();
            pseudographics.add("  " + reminder);
            pseudographics = combineAllResults();
        } catch (ArithmeticException ie) {
            System.out.println("You mustn't divided by zero");
            divisor = input("divisor");
        }
		output();
	}

    /**
     * Inputs a variable
     *
     * @param nameOfVariable   name of variable which we input
     * @return number which was inputted
     * @throws NumberFormatException
     * @throws IOException
     */
    public static int input(String nameOfVariable) throws NumberFormatException, IOException{
        System.out.println(String.format("Please, input %s", nameOfVariable));
        BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
        int number = Integer.parseInt(bf.readLine());
        return number;
    }

    /**
     * Finds sign of division of 2 number
     *
     * @return true if result of division "-", false if "+"
     */
    public static String isNegativeSign() {
        return integerResult = ((dividend < 0 && divisor > 0) || (dividend > 0 && divisor < 0)) ? "-" : "";
    }

    /**
     * Finds sign of 2 number and adds to list
     *
     */
    public static void isDividendLessZero() {
        pseudographics.add((dividend < 0) ? (" " + dividend + "|" + divisor) : ("  " + dividend + "|" + divisor));
        pseudographics.add(" -" + signPerDigits(howManyDigits(dividend), " "));
    }

    /**
     * Intermediate Counting from division
     *
     * @return reminder from division
     */
    public static int intermediateCounting() {
        int firstDividend;
        cursor = 1;
        firstDividend = numberLessDivisor(Character.getNumericValue(String.valueOf(dividend).codePointAt(0)));
        reminder = extractReminder(firstDividend);
        while(cursor < String.valueOf(dividend).length()){
            if(reminder == 0){
                pseudographics.add("  " + reminder);
                pseudographics.add(" -");
                reminder = extractReminder(Character.getNumericValue(String.valueOf(dividend).codePointAt(cursor)));
                cursor++;
            } else {
                reminder = numberLessDivisor(reminder);
                pseudographics.add("  " + reminder);
                pseudographics.add(" -");
                reminder = extractReminder(reminder);
            }
        }
        return reminder;
    }

    /**
     * Compile digits to digit of divisor
     *
     * @param number
     * @return number >= divisor
     */
    public static int numberLessDivisor(int number) {
        number = Math.abs(number);
        while(number < divisor){
            if(cursor >= String.valueOf(dividend).length()){
                break;
            }
            number = number * 10 + Character.getNumericValue(String.valueOf(dividend).codePointAt(cursor));
            cursor++;
        }
        return number;
    }

    /**
     * Finds amount of digits in number
     *
     * @param number
     * @return amount of digits in number
     */
	public static int howManyDigits(int number) {
		int count = 1;
		while (number / 10 != 0) {
			count++;
			number /= 10;
		}
		return count;
	}

    /**
     * Returns reminder from difference of number and multiply from max integer from number divides of divisor
     * Adds result to list
     * @param number
     * @return difference
     */
	public static int extractReminder(int number) {
		int integerDivision;
		int subtrahend;
		integerDivision = number / divisor;
		integerResult += integerDivision;
		subtrahend = integerDivision * divisor;
		pseudographics.add("  " + subtrahend);
		reminder = number - subtrahend;
		pseudographics.add(String.format("  " + signPerDigits(howManyDigits(subtrahend), "-")));
		return reminder;
	}

    /**
     * Creates string with set sign of length by amount of digits
     *
     * @param amountOfDigits
     * @param sign
     * @return string with set sign
     */
	public static String signPerDigits(int amountOfDigits, String sign){
		StringBuilder sb= new StringBuilder ("");
		int count = 0;
		while(count < amountOfDigits){
			sb.append(sign);
			count++;
		}
		return sb.toString();
	}

    /**
     * Combines results of divide
     *
     * @return list with all intermediate results
     */
	public static ArrayList<String> combineAllResults() {
        String p = (howManyDigits(divisor) > integerResult.length()) ?
                "|" + signPerDigits(howManyDigits(divisor), "-") : "|" + signPerDigits(integerResult.length(), "-");
		pseudographics.add(1, (pseudographics.get(1)) + p);
		pseudographics.remove(2);
		pseudographics.add(2, (pseudographics.get(2)  + signPerDigits(pseudographics.get(0).indexOf("|")-pseudographics.get(2).length(), " ") + "|" + integerResult));
		pseudographics.remove(3);
		return pseudographics;
	}

    /**
     * Outputs results from a list
     */
	public static void output (){
		for (String e : pseudographics){
			System.out.println(e);
		}
	}
}